/**
 * @@description 工具类
 */
var x_PI = 3.14159265358979324 * 3000.0 / 180.0;
var PI = 3.1415926535897932384626;
var a = 6378245.0;
var ee = 0.00669342162296594323;
class Util {
	constructor(viewer) {
		this._viewer = viewer;
		this._scene = viewer.scene;
	}

	/**
	 *@description  生成唯一标识
	 */
	generateUUID() {
		return Cesium.createGuid();
	}
	/**
	 * @description 经纬度坐标转Web墨卡托投影坐标
	 * @param {Object} lonLat
	 */
	convertLonlatToWebMercator(lonLat) {
		var webMercatorProjection = new Cesium.WebMercatorProjection();
		return webMercatorProjection.project(Cesium.Cartesian3.fromDegrees(lonLat.x, lonLat.y, lonLat.z));
	}

	/**
	 * @description 经纬度转世界坐标
	 * @param {Object} lonLat
	 */
	convertLonlatToWorld(lonLat) {
		return Cesium.Cartesian3.fromDegrees(lonLat.x, lonLat.y, lonLat.z)
	}

	/**
	 * @description 墨卡托投影转经纬度坐标
	 * @param {Object} mercator
	 */
	convertWebMercatorToLonlat(mercator) {}

	/**
	 * @description wgs84坐标转为gcj02坐标
	 * @param {Object} wgs84
	 */
	convertWgs84ToGcj02(wgs84) {
		let lng=wgs84.x;
		let lat=wgs84.y;
	   if (this.out_of_china(lng, lat)) {
			return [lng, lat]
		}
		else {
			var dlat = this.transformlat(lng - 105.0, lat - 35.0);
			var dlng = this.transformlng(lng - 105.0, lat - 35.0);
			var radlat = lat / 180.0 * PI;
			var magic = Math.sin(radlat);
			magic = 1 - ee * magic * magic;
			var sqrtmagic = Math.sqrt(magic);
			dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
			dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
			var mglat = lat + dlat;
			var mglng = lng + dlng;
			return {
				x:mglng,
				y:mglat,
				z:wgs84.z||0,
			}
		}
	}
	
	/**
	 * GCJ02 转换为 WGS84
	 * @param lng
	 * @param lat
	 * @returns 
	 */
	convertGcj02ToWgs84(GCJ02) {
		let lng=GCJ02.x;
		let lat=GCJ02.y;
	    if (this.out_of_china(lng, lat)) {
	        return [lng, lat]
	    }
	    else {
	        var dlat = this.transformlat(lng - 105.0, lat - 35.0);
	        var dlng = this.transformlng(lng - 105.0, lat - 35.0);
	        var radlat = lat / 180.0 * PI;
	        var magic = Math.sin(radlat);
	        magic = 1 - ee * magic * magic;
	        var sqrtmagic = Math.sqrt(magic);
	        dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
	        dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
	        mglat = lat + dlat;
	        mglng = lng + dlng;
	        return{
				x:lng * 2 - mglng,
				y:lat * 2 - mglat,
				z:GCJ02.z||0
			}
	    }
	}
	
	
	/**
	 * 判断是否在国内，不在国内则不做偏移
	 * @param lng
	 * @param lat
	 * @returns {boolean}
	 */
	out_of_china(lng, lat) {
	    return (lng < 72.004 || lng > 137.8347) || ((lat < 0.8293 || lat > 55.8271) || false);
	}
	
	transformlat(lng, lat) {
	    var ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
	    ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
	    ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
	    ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
	    return ret
	}

	transformlng(lng, lat) {
	    var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
	    ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
	    ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
	    ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
	    return ret
	}

	/**
	 * @description 屏幕坐标转世界坐标
	 * @param {Cartesian2} window
	 * @param {Object} noPickEntity
	 * @return {Cartesian3} 世界坐标
	 */
	convertWindowToWorld(window,noPickEntity) {
		var cartesian;
		var pickedObject;
		try {
			pickedObject = this._scene.pick(window, 5, 5);
		} catch (e) {
			console.log("scene.pick 拾取位置时异常",e);
		}

		if (this._scene.pickPositionSupported && Cesium.defined(pickedObject)) {
			var pcEntity = this.hasPickedModel(pickedObject, noPickEntity);
			if (!pcEntity) {
				cartesian = this._scene.pickPosition(window);
				if (Cesium.defined(cartesian)) {
					var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
					if (cartographic.height >= 0) return cartesian;
					if (!Cesium.defined(pickedObject.id) && cartographic.height >= -500) return cartesian;
				} else {}
			} else {}
		} else {}
		if (this._scene.onlyPickModelPosition) return cartesian;

		//提取鼠标点的地理坐标 
		if (this._scene.mode === Cesium.SceneMode.SCENE3D) {
			//三维模式下
			var pickRay = this._scene.camera.getPickRay(window);
			cartesian = this._scene.globe.pick(pickRay, this._scene);
		} else {
			//二维模式下
			cartesian = this._scene.camera.pickEllipsoid(window, this._scene.globe.ellipsoid);
		}
		if (Cesium.defined(cartesian) && this._scene.camera.positionCartographic.height < 10000) {
			var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
			if (cartographic.height < -5000) return null; //屏蔽无效值
		}
		return cartesian;
	}

	/**
	 * @description 世界坐标转屏幕坐标
	 * @param {Cartesian3} world: 世界坐标
	 * @return {Cartesian2} 屏幕坐标
	 */
	convertWorldToWindow(world) {
		return Cesium.SceneTransforms.wgs84ToWindowCoordinates(this._scene, world)
	}

	/**
	 * @description 世界坐标转经纬度
	 * @param {Cartesian3} world
	 * @return {Cartographic}
	 */
	convertWorldToLonlat(world) {
		var ellipsoid=this._scene.globe.ellipsoid;
		var cartographic=ellipsoid.cartesianToCartographic(world);
		var lat=Cesium.Math.toDegrees(cartograhphic.latitude);
		var lng=Cesium.Math.toDegrees(cartograhpinc.longitude);
		var alt=cartographic.height;
		return {
			x:lng,
			y:lat,
			z:alt,
		}
	}

	/**
	 * @description 创建天空和太阳,默认会替代之前设置的光源
	 */
	createSkyAndSun() {}

	/**
	 * @description 根据经纬度和方位角得到可以使物体贴地的欧拉角
	 * @param {Object} lonlat 经纬度
	 * @param {Object} angle 方位角 默认0
	 */
	getAnglesFromLonlat(lonlat, angle) {}

	/**
	 * @description 根据世界坐标和方位角得到可以使物体贴地的旋转信息
	 * @param {Object} pos 世界坐标 
	 * @param {Object} angle 方位角 默认0
	 */
	getAnglesFromPosition(pos, azimuth) {}

	/**
	 * @description 计算两点间的方位角
	 * @param {Object} lonlat1 起点经纬度
	 * @param {Object} lonlat2 终点经纬度
	 * @return {number}  方位角
	 */
	getAzimuth(lonlat1, lonlat2) {}

	/**
	 * @description 获取多边形中心点
	 * @param {Object} coordinates 多边形经纬度坐标数组 [[x,y],[x,y],[x,y]......] (注:仅支持二维的经纬度数组)
	 * @return {Object}  中心点坐标
	 */
	getCenterCoordinates(coordinates) {}

	/**
	 * @description 获取多边形重心
	 * @param {Object} coordinates 多边形经纬度坐标数组 [[x,y],[x,y],[x,y]......] (注:仅支持二维的经纬度数组)
	 * @return {Object}  重心点坐标
	 */
	getCenterOfGravityPoint(coordinates) {}

	/**
	 * @description 计算两点间的欧式距离 单位:米
	 * @param {Object} lonlat1 起点经纬度
	 * @param {Object} lonlat2 终点经纬度
	 * @return {number}  欧式距离
	 */
	getEuclideanDistance(lonlat1, lonlat2) {}

	/**
	 * @description 计算线的长度单位:米
	 * @param {Object} coords 经纬度
	 * @param {Boolean} isSpherical 是否计算球面距离 默认true 如果传入false 则计算欧氏距离
	 * @return {number} 
	 */
	getLineLength(coords, isSpherical) {}

	/**
	 * @description 获取多边形的范围
	 * @param {Object} coordinates 多边形经纬度坐标数组 [[x,y],[x,y],[x,y]......] 支持Polygon和MultiPolygon
	 * @return {Object}  多边形的范围
	 */
	getPolygonExtent(coordinates) {}

	/**
	 * @description 计算多边形的球面面积
	 * @param {Array} coords 多边形的坐标
	 * @return {number}  球面面积 单位平方米
	 */
	getSphericalArea(coords) {}

	/**
	 * @description 计算两点间的球面距离 单位:米
	 * @param {Object} lonlat1 起点经纬度
	 * @param {Object} lonlat2 终点经纬度
	 * @return {number}  球面距离
	 */
	getSphericalDistance(lonlat1, lonlat2) {}

	hasPickedModel(pickedObject, noPickEntity) {
		if (Cesium.defined(pickedObject) && Cesium.defined(noPickEntity)) {
			if (Cesium.defined(noPickEntity.id) && Cesium.defined(pickedObject.id)) {
				if (Cesium.defined(noPickEntity.id.id) && Cesium.defined(pickedObject.id.id) && noPickEntity.id
					.id == pickedObject.id.id) {
					return true
				} else if (noPickEntity.id == pickedObject.id) {
					return true
				}
			}
		}
		return false;
	}

}
export {
	Util
};
